<template>
  <ele-upload-list
    :limit="limit"
    :drag="true"
    v-model="data"
    :item-style="itemStyle"
    :button-style="buttonStyle"
    @upload="onUpload"
    @retry="(item) => onUpload(item, true)"
    @remove="onRemove"
    :multiple="multiple"
    :readonly="readOnly"
  />
</template>

<script setup>
  import { ref, watch } from 'vue';
  import { EleMessage } from 'ele-admin-plus/es';
  import axios from 'axios';
  import { getToken } from '@/api/qiniu';

  const props = defineProps({
    /** 绑定值 */
    modelValue: String,
    /** 选择数量限制 */
    limit: Number,
    /** 文件大小限制, 单位MB */
    fileLimit: {
      type: Number,
      default: 20
    },
    multiple: {
      type: Boolean,
      default: true
    },
    /** 自定义样式 */
    itemStyle: Object,
    /** 自定义上传按钮样式 */
    buttonStyle: Object,
    /** 上传按钮 */
    readOnly: {
      type: Boolean,
      default: false
    }
  });

  const emit = defineEmits(['update:modelValue', 'change']);

  /** 数据 */
  const data = ref([]);

  /** 上传事件 */
  const onUpload = (d, retry) => {
    if (!d.file) {
      return;
    }
    if (!d.file.type.startsWith('image')) {
      EleMessage.error('只能选择图片');
      return;
    }
    if (d.file.size / 1024 / 1024 > props.fileLimit) {
      EleMessage.error(`大小不能超过 ${props.fileLimit}MB`);
      return;
    }
    if (!retry) {
      data.value.push({ ...d });
    }
    const item = data.value.find((t) => t.key === d.key);
    if (!item) {
      return;
    }
    item.status = 'uploading';
    uploadQiniu(d.file)
      .then((res) => {
        console.log(res);
        item.status = 'done';
        item.url = imagesUrl.value + res.key;
      })
      .catch((e) => {
        item.status = 'exception';
        EleMessage.error(e.message);
      });
  };

  /** 删除事件 */
  const onRemove = (item) => {
    data.value.splice(data.value.indexOf(item), 1);
  };

  /** 更新绑定值 */
  const updateModelValue = (value) => {
    if (props.modelValue !== value) {
      emit('update:modelValue', value);
      emit('change', value);
    }
  };

  /** 判断是否全部上传完成 */
  const isDone = () => {
    return !data.value.some((d) => d.status !== 'done');
  };

  /** 获取已上传的图片地址 */
  const getDataValue = () => {
    return data.value.map((d) => d.url);
  };

  // 同步绑定值
  watch(
    data,
    () => {
      const res = getDataValue();
      if (props.limit === 1) {
        updateModelValue(res.join());
        return;
      }
      updateModelValue(res.length ? JSON.stringify(res) : '');
    },
    { deep: true }
  );

  watch(
    () => props.modelValue,
    (value) => {
      if (!value) {
        if (data.value.length) {
          data.value = [];
        }
        return;
      }
      if (props.limit === 1) {
        if (
          data.value.length === 1 &&
          data.value[0].url === value /* &&
        data.value[0].status === 'done' */
        ) {
          return;
        }
        data.value = [{ key: `0-${value}`, url: value, status: 'done' }];
        return;
      }
      try {
        const temp = JSON.parse(value);
        if (
          temp.length === data.value.length &&
          JSON.stringify(getDataValue()) === value
        ) {
          return;
        }
        data.value = temp.map((t, i) => {
          return { key: `${i}-${t}`, url: t, status: 'done' };
        });
      } catch (e) {
        console.error(e);
        data.value = [];
      }
    },
    { immediate: true }
  );

  defineExpose({ isDone });

  // 七牛
  const uploadUrl = ref('');
  const imagesUrl = ref('');
  /** 上传七牛用到的参数 */
  const postData = ref({
    token: '',
    key: '',
    file: {}
  });
  const getQiniuToken = () => {
    getToken({})
      .then((res) => {
        postData.value.token = res.token;
        uploadUrl.value = res.uploadUrl;
        imagesUrl.value = res.imagesUrl;
      })
      .catch((e) => {
        console.log(e);
      });
  };
  const uploadQiniu = async (request) => {
    const promise = new Promise((resolve, reject) => {
      const config = {
        headers: { 'Content-Type': 'multipart/form-data' }
      };
      const filePath = request.name;
      // 获取最后一个.的位置
      var index = filePath.lastIndexOf('.');
      // 获取后缀
      var ext = filePath.substr(index + 1);
      // 输出结果
      const key = `${new Date().getTime()}${Math.floor(
        Math.random() * 100
      )}.${ext}`; // 自定义文件名
      console.log(request);
      const fd = new FormData();
      fd.append('file', request);
      fd.append('token', postData.value.token);
      fd.append('key', key);
      // console.log(this.axios)
      axios
        .post(uploadUrl.value, fd, config)
        .then((res) => {
          if (res.status === 200 && res.data) {
            resolve(res.data);
          } else {
            reject(res);
          }
        })
        .catch((err) => {
          console.log(err);
          EleMessage.error({
            message: `上传失败[${err.status}]`,
            duration: 2000
          });
        });
    });
    return promise;
  };
  getQiniuToken();
</script>
